package top.goldenyear.porpoise.infra.storage.service;

import cn.hutool.v7.core.convert.ConvertUtil;
import cn.hutool.v7.core.data.id.IdUtil;
import cn.hutool.v7.core.io.file.FileNameUtil;
import com.easy.query.api.proxy.client.EasyEntityQuery;
import com.easy.query.solon.annotation.Db;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.UploadedFile;
import top.goldenyear.porpoise.common.core.exception.ErrorCode;
import top.goldenyear.porpoise.common.core.exception.ServiceException;
import top.goldenyear.porpoise.common.core.model.Ret;
import top.goldenyear.porpoise.framework.web.core.model.PageResult;
import top.goldenyear.porpoise.framework.web.core.model.query.QPage;
import top.goldenyear.porpoise.framework.web.core.service.BaseService;
import top.goldenyear.porpoise.framework.web.core.util.WebUtils;
import top.goldenyear.porpoise.infra.storage.config.FileConfig;
import top.goldenyear.porpoise.infra.storage.core.model.Media;
import top.goldenyear.porpoise.infra.storage.core.util.FileClientUtils;
import top.goldenyear.porpoise.infra.storage.model.StorageConfig;
import top.goldenyear.porpoise.infra.storage.model.StorageFile;
import top.goldenyear.porpoise.infra.storage.model.proxy.StorageFileProxy;

/**
 * 文件存储表 Service 服务层
 *
 * @author airhead
 * @since 2024-10-16
 */
@Component
@Slf4j
public class StorageFileService extends BaseService<StorageFile, StorageFileProxy> {
  @Db private EasyEntityQuery easyEntityQuery;
  @Inject private StorageConfigService storageConfigService;

  public StorageFileService() {
    super(StorageFile.class, StorageFileProxy.class);
  }

  public Boolean createFile(StorageFile storageFile) {
    return save(storageFile);
  }

  public Boolean updateFile(StorageFile storageFile) {
    return updateById(storageFile);
  }

  public StorageFile getFile(Integer id) {
    return getById(id);
  }

  public Boolean deleteFile(Integer id) {
    return deleteById(id);
  }

  public List<StorageFile> listFile(StorageFile files) {
    return list(files);
  }

  public PageResult<StorageFile> paginateFile(QPage qPage, StorageFile files) {
    return paginate(qPage, files);
  }

  public StorageFile uploadFile(Integer configId, UploadedFile file) throws IOException {
    StorageConfig storageConfig = storageConfigService.getByIdOrMaster(configId);
    if (storageConfig == null) {
      throw new ServiceException(ErrorCode.builder().code(500).msg("未配置存储").build());
    }

    String cfgId = ConvertUtil.toStr(storageConfig.getId());
    String fileName = file.getName();
    String suffix = FileNameUtil.getSuffix(fileName);
    String targetFileName = String.format("%s.%s", IdUtil.fastSimpleUUID(), suffix);

    Media media = Media.of(fileName, file.getContent(), file.getContentSize());
    Ret ret = FileClientUtils.use(cfgId).put(targetFileName, media);
    if (ret.isFail()) {
      throw new ServiceException(ErrorCode.builder().code(500).msg("存储文件错误").build());
    }

    FileConfig fileConfig =
        FileConfig.of(storageConfig.getStorageType(), storageConfig.getConfig());
    String domain = fileConfig.getDomain();

    String url =
        String.format(
            "%s/admin-api/infra/storage/storageFile/%s/%s", domain, cfgId, targetFileName);
    StorageFile storageFiles = new StorageFile();
    storageFiles.setConfigId(storageConfig.getId());
    storageFiles.setName(fileName);
    storageFiles.setType(suffix);
    storageFiles.setSize(file.getContentSize());
    storageFiles.setUrl(url);
    storageFiles.setPath(targetFileName);
    save(storageFiles);

    return storageFiles;
  }

  public List<StorageFile> uploadFiles(Integer configId, List<UploadedFile> files)
      throws IOException {
    List<StorageFile> storageFiles = new ArrayList<>();
    for (UploadedFile file : files) {
      StorageFile sf = uploadFile(configId, file);
      storageFiles.add(sf);
    }

    return storageFiles;
  }

  public void download(Context context, Integer configId, String fileName) throws IOException {
    StorageFile storageFile =
        entityQueryable()
            .where(storageFileProxy -> storageFileProxy.path().eq(fileName))
            .firstOrNull();
    if (storageFile == null) {
      context.status(404);
      return;
    }

    StorageConfig storageConfig = storageConfigService.getByIdOrMaster(configId);
    if (storageConfig == null) {
      context.status(404);
      return;
    }

    String cfgId = ConvertUtil.toStr(storageConfig.getId());
    FileConfig fileConfig =
        FileConfig.of(storageConfig.getStorageType(), storageConfig.getConfig());
    Media media = FileClientUtils.use(cfgId).get(fileConfig.getBucket(), storageFile.getPath());
    WebUtils.renderFile(context, fileName, media.contentType(), media.body());
  }

  @Override
  protected EasyEntityQuery easyEntityQuery() {
    return easyEntityQuery;
  }
}
